<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Support\Str;
use Carbon\Carbon;

class BookInvitation extends Model
{
    use HasFactory;

    protected $fillable = [
        'book_id',
        'inviter_id',
        'token',
        'expires_at',
        'is_used',
        'used_by',
        'used_at',
    ];

    protected $casts = [
        'expires_at' => 'datetime',
        'used_at' => 'datetime',
        'is_used' => 'boolean',
    ];

    /**
     * 生成邀请令牌
     */
    public static function generateToken(): string
    {
        do {
            $token = Str::random(32);
        } while (self::where('token', $token)->exists());
        
        return $token;
    }

    /**
     * 创建邀请
     */
    public static function createInvitation(int $bookId, int $inviterId, int $expiryHours = 72): self
    {
        return self::create([
            'book_id' => $bookId,
            'inviter_id' => $inviterId,
            'token' => self::generateToken(),
            'expires_at' => Carbon::now()->addHours($expiryHours),
        ]);
    }

    /**
     * 检查邀请是否有效
     */
    public function isValid(): bool
    {
        return !$this->is_used && $this->expires_at->isFuture();
    }

    /**
     * 使用邀请
     */
    public function use(int $userId): bool
    {
        if (!$this->isValid()) {
            return false;
        }

        $this->update([
            'is_used' => true,
            'used_by' => $userId,
            'used_at' => Carbon::now(),
        ]);

        return true;
    }

    /**
     * 关联账本
     */
    public function book(): BelongsTo
    {
        return $this->belongsTo(MoneyBook::class, 'book_id');
    }

    /**
     * 关联邀请人
     */
    public function inviter(): BelongsTo
    {
        return $this->belongsTo(User::class, 'inviter_id');
    }

    /**
     * 关联使用者
     */
    public function usedBy(): BelongsTo
    {
        return $this->belongsTo(User::class, 'used_by');
    }

    /**
     * 清理过期邀请
     */
    public static function cleanExpired(): int
    {
        return self::where('expires_at', '<', Carbon::now())
                   ->where('is_used', false)
                   ->delete();
    }
}